package uk.co.richardwkirk.parkrun.funnels.display;

import java.util.LinkedList;
import java.util.Stack;

import uk.co.richardwkirk.parkrun.funnels.model.Funnel;
import uk.co.richardwkirk.parkrun.funnels.model.Runner;

public class CommandLineDisplay extends FunnelDisplay {

	public CommandLineDisplay(DisplaySettings settings) {
		super(settings);
	}


	private char queueLetter(int queue) {
		return (char)(queue % 8 + 65);
	}

	private String showBuffer() {
		StringBuilder bufferImage = new StringBuilder();
		bufferImage.append(" > ");
		LinkedList<Runner> buffer = funnels.getBuffer();
		for (int i = 0; i < funnels.getBufferSize() - buffer.size(); ++i)
		{
			bufferImage.append("_");
		}
		Stack<String> stackRunners = new Stack<String>();
		for (int i = 0; i < buffer.size(); ++i) {
			stackRunners.push("O");
		}
		for (String marker : stackRunners) {
			bufferImage.append(marker);
		}
		bufferImage.append(" > ");
		return bufferImage.toString();
	}

	private String showFunnelState(Funnel funnel) {
		StringBuilder funnelImage = new StringBuilder();
		String funnelEntrySymbol = " | ";
		if (funnels.isFillFunnel(funnel)) {
			funnelEntrySymbol = " > ";
		}
		funnelImage.append(funnelEntrySymbol).append(funnel.getName()).append(funnelEntrySymbol);
		for (int i = funnel.getNumberOfPlaces() - 1; i >= 0; --i) {
			Funnel.FunnelledRunner nextRunner = funnel.getRunnerAt(i);
			if (nextRunner == null) {
				funnelImage.append("_");
			}
			else {
				funnelImage.append(getRunnerMarker(nextRunner));
			}
		}
		if (funnels.isExitFunnel(funnel)) {
			funnelImage.append(" >>> ");
		}
		else {
			funnelImage.append("|");
		}
		return funnelImage.toString();
	}

	private char getRunnerMarker(Funnel.FunnelledRunner nextRunner) {
		if (nextRunner.runner.getName().equals("Jennifer MELBOURNE")) {
			return 'j';
		}
		else if (nextRunner.runner.getName().equals("Andrew MELBOURNE")) {
			return 'a';
		}
		else if (nextRunner.runner.getName().equals("Richard William KIRK")) {
			return 'r';
		}
		else if (nextRunner.runner.getName().equals("Victoria KIRK")) {
			return 'v';
		}
		else {
			return queueLetter(nextRunner.queue);
		}
	}

	/* (non-Javadoc)
	 * @see uk.co.richardwkirk.display.FunnelDisplay#setStatus(java.lang.String)
	 */
	@Override
	public void setStatus(String status) {
		System.out.println(status);
	}

	@Override
	public void setOverflowed(boolean b) {
		funnelOverflowed = b;
	}


	@Override
	public void showTime(String time) {
		System.out.println(time);
	}


	@Override
	protected void showCurrentState() {
		StringBuilder bufferImage = new StringBuilder();
		bufferImage.append(showBuffer());
		boolean resetBuffer = false;
		
		StringBuilder funnelDisplay = new StringBuilder();
		StringBuilder funnelImage = new StringBuilder();
		funnelDisplay.append(" : ");
		int totalRunners = 0;
		for (Funnel funnel : funnels.getFunnels())
		{
			int numberOfRunnersInFunnel = funnel.getNumberOfRunners();
			funnelDisplay.append(funnel.getName()).append("=").append(numberOfRunnersInFunnel).append(" ");
			totalRunners += numberOfRunnersInFunnel;
			funnelImage.append(bufferImage.toString());
			if (!resetBuffer) {
				int bufferImageLength = bufferImage.length();
				bufferImage = new StringBuilder();
				for (int i = 0; i < bufferImageLength; ++i) {
					bufferImage.append(" ");
				}
				resetBuffer = true;
			}
			funnelImage.append(showFunnelState(funnel)).append(("\n"));
		}
		funnelDisplay.append(">>> Total = ").append(totalRunners);
		int overflow = funnels.getOverflowSize();
		funnelDisplay.append(", Overflow = ").append(overflow);
		
		System.out.println("---------------------------------------------------------------------------------------");
		System.out.println(funnelDisplay.toString());
		System.out.println(funnelImage.toString());
		if (funnelOverflowed) {
			System.out.print("*** FUNNEL OVERFLOWED ***  - Current overflow = ");
			System.out.println(overflow);
		}
		else {
			System.out.println();
		}
		System.out.println("Filling queue: " + queueLetter(funnels.getFillQueue()) + ", Draining queue: " + queueLetter(funnels.getDrainQueue()));
		System.out.println("Average time in funnel: " + funnels.getAverageTimeSpent() + ", Maximum time in funnel: " + funnels.getMaximumTimeSpent());
	}

}
